#include "watchpoint.h"
#include "expr.h"

#define NR_WP 32

static WP wp_pool[NR_WP];
static WP *head, *free_;

void init_wp_pool() {
    int i;
    for (i = 0; i < NR_WP; i++) {
        wp_pool[i].NO = i;
        wp_pool[i].next = &wp_pool[i + 1];
        wp_pool[i].exp = (char*) malloc(32 * 32);
    }
    wp_pool[NR_WP - 1].next = NULL;

    head = NULL;
    free_ = wp_pool;
}

WP *new_wp() {
    Assert(free_ != NULL, "no more free watchpoint!");
    WP *wp = free_;
    //free_指针后移
    free_ = free_->next;
    //wp进入head队头
    wp->next = head;
    head = wp;
    return wp;
}

void free_wp(WP *wp) {
    WP *tmp = head;
    //wp出head队列
    if (head != wp) {
        while (tmp->next != wp) {
            tmp = tmp->next;
        }
        tmp->next = wp->next;
    } else {
        head = wp->next;
    }
    //wp入free_队头
    wp->next = free_;
    free_ = wp;
    printf("remove a WP:[%d]\n",wp->NO);
}

void free_wp_no(int no) {
    WP *wp = head;
    while (wp->NO != no) {
        wp = wp->next;
    }
    free_wp(wp);
}

void list_used_wps() {
    if (head == NULL) {
        printf("There is no working WP.\n");
        return;
    }
    WP *wp = head;
    while (wp != NULL) {
        printf("No.%d watching: [%s]=[%d]\n", wp->NO, wp->exp, wp->value);
        wp = wp->next;
    }
}

bool check() {
    WP *wp = head;
    bool success = false, check = false;
    uint32_t result;
    while (wp != NULL) {
        result = expr(wp->exp, &success);
        if (!success) {
            printf("Can't calculate value of the EXP of [No.%d] WP.\n",wp->NO);
//            free_wp_no(wp->NO);
//            wp = wp->next;
//            continue;
        } else if (result != wp->value) {
            printf("No.%d WP triggered!\n", wp->NO);
            check = true;
            wp->value = result;
//            free_wp_no(wp->NO);
        }
        wp = wp->next;
    }
    return check;
}

